home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / admin / xinetd.2 / xinetd / xinetd.2.1.7-linux.4 / libs / src / xlog / filelog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-24  |  6.4 KB  |  302 lines

  1. /*
  2.  * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: filelog.c,v 1.1 1995/11/11 23:08:58 chuck Exp root $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <varargs.h>
  12. #include <fcntl.h>
  13. #include <time.h>
  14. #ifndef NO_SYSLOG
  15. #include <syslog.h>
  16. #else
  17. #define LOG_ALERT                0
  18. #endif
  19.  
  20. #include "sio.h"
  21.  
  22. #include "xlog.h"
  23. #include "impl.h"
  24. #include "filelog.h"
  25.  
  26. PRIVATE int filelog_init() ;
  27. PRIVATE void filelog_fini() ;
  28. PRIVATE int filelog_control() ;
  29. PRIVATE int filelog_write() ;
  30. PRIVATE int filelog_parms() ;
  31. PRIVATE int limit_checks() ;
  32.  
  33. struct xlog_ops __xlog_filelog_ops = 
  34.     {
  35.         filelog_init,
  36.         filelog_fini,
  37.         filelog_write,
  38.         filelog_control,
  39.         filelog_parms
  40.     } ;
  41.  
  42.  
  43. PRIVATE int filelog_init( xp, ap )
  44.     xlog_s    *xp ;
  45.     va_list    ap ;
  46. {
  47.     int                fd ;
  48.     struct stat        st ;
  49.     struct filelog *flp ;
  50.     char                *filename    = va_arg( ap, char * ) ;
  51.     int                flags            = va_arg( ap, int ) ;
  52.  
  53.     flp = NEW( struct filelog ) ;
  54.     if ( flp == NULL )
  55.         return( XLOG_ENOMEM ) ;
  56.  
  57.     /*
  58.      * For safety, don't open a logfile if it's a symlink - cdm
  59.      */
  60.     if ( lstat ( filename, &st ) != 0 )
  61.         return( XLOG_EOPEN ) ;
  62.     if ( ( st.st_mode & S_IFLNK ) == S_IFLNK )
  63.     {
  64. #ifndef NO_SYSLOG
  65.         syslog(LOG_WARNING, "Log file %s is a symlink - open abort", filename);
  66. #endif /* NO_SYSLOG */
  67.         return( XLOG_EOPEN ) ;
  68.     }
  69.  
  70.     if ( flags & O_CREAT )
  71.         fd = open( filename, flags, va_arg( ap, int ) ) ;
  72.     else
  73.         fd = open( filename, flags ) ;
  74.  
  75.     if ( fd == -1 )
  76.     {
  77.         FREE( flp ) ;
  78.         return( XLOG_EOPEN ) ;
  79.     }
  80.     
  81.     FILELOG_DISABLE_SIZE_CONTROL( flp ) ;
  82.     (void) Sbuftype( fd, SIO_LINEBUF ) ;
  83.     flp->fl_fd = fd ;
  84.     flp->fl_state = FL_OPEN ;
  85.     xp->xl_data = flp ;
  86.     return( XLOG_ENOERROR ) ;
  87. }
  88.  
  89.  
  90. PRIVATE void filelog_fini( xp )
  91.     xlog_s *xp ;
  92. {
  93.     struct filelog *flp = FILELOG( xp ) ;
  94.  
  95.     if ( flp->fl_state != FL_CLOSED )
  96.     {
  97.         (void) close( flp->fl_fd ) ;
  98.         flp->fl_state = FL_CLOSED ;
  99.     }
  100.     FREE( flp ) ;
  101.     xp->xl_data = NULL ;
  102. }
  103.  
  104.  
  105.  
  106. PRIVATE int filelog_control( xp, cmd, ap )
  107.     xlog_s        *xp ;
  108.     xlog_cmd_e    cmd ;
  109.     va_list        ap ;
  110. {
  111.     struct stat        st ;
  112.     struct filelog *flp        = FILELOG( xp ) ;
  113.     int                status    = XLOG_ENOERROR ;
  114.  
  115.     if ( flp->fl_state == FL_ERROR )
  116.         return( flp->fl_error ) ;
  117.  
  118.     switch ( cmd )
  119.     {
  120.         case XLOG_GETFD:
  121.             if ( flp->fl_state == FL_OPEN )
  122.                 *va_arg( ap, int * ) = flp->fl_fd ;
  123.             else
  124.                 status = XLOG_ENOERROR ;
  125.             break ;
  126.  
  127.         case XLOG_LIMITS:
  128.             flp->fl_soft_limit = va_arg( ap, unsigned ) ;
  129.             flp->fl_hard_limit = va_arg( ap, unsigned ) ;
  130.             flp->fl_issued_warning = FALSE ;
  131.             FILELOG_ENABLE_SIZE_CONTROL( flp ) ;
  132.             flp->fl_state = FL_OPEN ;
  133.             /* FALL THROUGH */
  134.  
  135.         case XLOG_SIZECHECK:
  136.             if ( ! FILELOG_SIZE_CONTROL( flp ) )
  137.                 break ;
  138.             if ( fstat( flp->fl_fd, &st ) == -1 )
  139.             {
  140.                 FILELOG_DISABLE_SIZE_CONTROL( flp ) ;
  141.                 flp->fl_state = FL_ERROR ;
  142.                 flp->fl_error = status = XLOG_EFSTAT ;
  143.             }
  144.             else
  145.             {
  146.                 flp->fl_size = st.st_size ;
  147.                 if ( flp->fl_size > flp->fl_soft_limit )
  148.                     status = limit_checks( xp ) ;
  149.             }
  150.             break ;
  151.     }
  152.     return( status ) ;
  153. }
  154.  
  155.  
  156. PRIVATE int limit_checks( xp )
  157.     xlog_s *xp ;
  158. {
  159.     struct filelog *flp = FILELOG( xp ) ;
  160.     char buf[ 100 ] ;
  161.  
  162.     if ( ! flp->fl_issued_warning )
  163.     {
  164.         if ( xp->xl_use != NULL )
  165.             xlog_write( (xlog_h) xp->xl_use, buf,
  166.                 strx_nprint( buf, sizeof( buf ),
  167.                                     "soft limit exceeded on '%s'", xp->xl_id ),
  168.                     XLOG_NOFLAGS, LOG_ALERT ) ;
  169.         flp->fl_issued_warning = TRUE ;
  170.     }
  171.  
  172.     if ( flp->fl_size <= flp->fl_hard_limit )
  173.         return( XLOG_ENOERROR ) ;
  174.     
  175.     if ( xp->xl_use != NULL )
  176.         xlog_write( (xlog_h) xp->xl_use, buf,
  177.             strx_nprint( buf, sizeof( buf ),
  178.                         "hard limit exceeded on '%s'; log closed", xp->xl_id ),
  179.                 XLOG_NOFLAGS, LOG_ALERT ) ;
  180.     flp->fl_state = FL_ERROR ;
  181.     return( XLOG_ESIZE ) ;
  182. }
  183.  
  184.  
  185. PRIVATE int filelog_write( xp, buf, len, flags, ap )
  186.     xlog_s    *xp ;
  187.     char        buf[] ;
  188.     int        len ;
  189.     int        flags ;
  190.     va_list    ap ;
  191. {
  192.     struct filelog    *flp                = FILELOG( xp ) ;
  193.     int                 action_flags    = ( xp->xl_flags | flags ) ;
  194.     int                msglen            = 0 ;
  195.     char                *percent_m_pos ;
  196.     struct stat        st ;
  197.     int                cc ;
  198.     int                status ;
  199.     time_t             current_time ;
  200.     struct tm        *tmp ;
  201.     time_t            time() ;
  202.  
  203.     if ( flp->fl_state != FL_OPEN )
  204.         return( flp->fl_error ) ;
  205.  
  206.     /*
  207.      * For safety, don't write a logfile if it's a symlink - cdm
  208.      * BOGUS - this should really be done by a separate daemon
  209.      */
  210.  
  211. #if 0
  212.     if ( fstat ( flp->fl_fd, &st ) != 0 )
  213.     {
  214.         flp->fl_state = FL_ERROR ;
  215.         flp->fl_error = XLOG_EFSTAT ;
  216.     }
  217.     if ( ( st.st_mode & S_IFLNK ) == S_IFLNK )
  218.     {
  219.         flp->fl_state = FL_ERROR ;
  220.         flp->fl_error = XLOG_EFSTAT ;
  221.     }
  222. #endif
  223.  
  224.     (void) time( ¤t_time ) ;
  225.     tmp = localtime( ¤t_time ) ;
  226.     cc = Sprint( flp->fl_fd, "%d/%d/%d@%02d:%02d:%02d",
  227.                             tmp->tm_year, tmp->tm_mon+1, tmp->tm_mday,
  228.                             tmp->tm_hour, tmp->tm_min, tmp->tm_sec ) ;
  229.     msglen += cc ;
  230.  
  231.     if ( action_flags & XLOG_PRINT_ID )
  232.     {
  233.         cc = Sprint( flp->fl_fd, " %s", xp->xl_id ) ;
  234.         msglen += cc ;
  235.     }
  236.  
  237.     if ( action_flags & XLOG_PRINT_PID )
  238.     {
  239.         cc = Sprint( flp->fl_fd, "[%d]", getpid() ) ;
  240.         msglen += cc ;
  241.     }
  242.  
  243.     cc = Sprint( flp->fl_fd, ": " ) ;
  244.     msglen += cc ;
  245.  
  246.     if ( ( action_flags & XLOG_NO_ERRNO ) ||
  247.                         ( percent_m_pos = __xlog_add_errno( buf, len ) ) == NULL )
  248.     {
  249.         cc = Swrite( flp->fl_fd, buf, len ) ;
  250.         msglen += cc ;
  251.     }
  252.     else
  253.     {
  254.         char errno_buf[ 100 ] ;
  255.         unsigned size = sizeof( errno_buf ) ;
  256.         int cc_before_errno = percent_m_pos - buf ;
  257.         char *ep ;
  258.  
  259.         /*
  260.          * The reason for the repetition of "msglen += cc ;" is that in the
  261.          * future we may want to check cc for SIO_ERR
  262.          */
  263.         ep = __xlog_explain_errno( errno_buf, &size ) ;
  264.         cc = Swrite( flp->fl_fd, buf, cc_before_errno ) ;
  265.         msglen += cc ;
  266.         cc = Swrite( flp->fl_fd, ep, (int)size ) ;
  267.         msglen += cc ;
  268.         cc = Swrite( flp->fl_fd, percent_m_pos+2, len-cc_before_errno-2 ) ;
  269.         msglen += cc ;
  270.     }
  271.     /*
  272.      * Writing a newline will cause a buffer flush since we asked for
  273.      * line-buffered output
  274.      */
  275.     Sputchar( flp->fl_fd, '\n' ) ;
  276.     msglen++ ;
  277.  
  278.     /*
  279.      * NOTE: we don't check if XLOG_NO_SIZECHECK is set in xp->xl_flags
  280.      *            because size control is off by default and in order to
  281.      *            be enabled XLOG_LIMITS must be used which overrides xp->xl_flags
  282.      */
  283.     if ( ! FILELOG_SIZE_CONTROL( flp ) || ( flags & XLOG_NO_SIZECHECK ) )
  284.         return( XLOG_ENOERROR ) ;
  285.  
  286.     flp->fl_size += msglen ;
  287.     if ( flp->fl_size <= flp->fl_soft_limit || 
  288.                     ( status = limit_checks( xp ) ) == XLOG_ENOERROR )
  289.         return( XLOG_ENOERROR ) ;
  290.     
  291.     flp->fl_state = FL_SIZE ;
  292.     return( status ) ;
  293. }
  294.  
  295.  
  296. PRIVATE int filelog_parms( ap )
  297.     va_list ap ;
  298. {
  299.     return( XLOG_ENOERROR ) ;
  300. }
  301.  
  302.